/*
 * Middleware
 * Copyright (C) 2010/11
 * Riccardo Pulvirenti, Giuseppe Ravidà, Andrea Tino
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANDABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses
 */

/*!
 * File: core.hpp
 */

#ifndef _CORE_HPP_
#define _CORE_HPP_

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <boost/thread/mutex.hpp>
#include <boost/thread.hpp>
#include <boost/lexical_cast.hpp>
#include <exception>
#include <xercesc/dom/DOMImplementation.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/dom/DOMNodeList.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>

#include "core_exception.hpp"
#include "worker_descriptor.hpp"
#include "common_types.hpp"
#include "xml_syn_logging.hpp"
#include "address.hpp"

//-----------------------------------------------------------------------------
// Constants
namespace middleware {
/*!
 * Default xml configuration file name.
 */
const std::string kXmlConfigFileName = "core.config.xml";
/*!
 * Default log file name.
 */
const std::string kLogFileName = "logfile";
}
//-----------------------------------------------------------------------------
// Configuration parameters
namespace middleware {
/*!
 * Output etiquette.
 */
const std::string kCOREEtq = "CORE:      ";
/*!
 * Used to get all configuration file info.
 */
typedef struct {
	/*!
	 * Name of the peer.
	 */
	std::string PeerId;
	/*!
	 * Peer's network interface.
	 */
	Address PeerAddress;
	/*!
	 * Peer's log CTA port.
	 */
	CTAPort LogCTAPort;
	/*!
	 * Peer's capabilities.
	 */
	WorkerCapabilities PeerCapabilities;
	/*!
	 * Peer's neighbourhood.
	 */
	std::vector< Address > PeerNeighbourhood;
} PeerConfiguration;
}
//-----------------------------------------------------------------------------
// Class definitions
namespace middleware {
/*! \class CORE
 * \brief Logic entry point for the application.
 *
 * Defines the entry point of the application. CORE provides services to grab
 * configuration file and look for parameters. It also configures UI, Manager,
 * WorkerDiscovery and Worker and runs them as four separate threads.
 */
class CORE {
public:
	/*!
	 * Constructor. Initializes file name to default (kConfigFileName).
	 * Log files postfix are set to random value.
	 */
	CORE();
	/*!
	 * Constructor. Initializes CORE providing a specific configuration file,
	 * different from the default one, and also specifies which prefix to use
	 * for log files.
	 */
	CORE(const std::string& config_filename, const std::string& config_peerid);
	/*!
	 * Destructor.
	 */
	~CORE();
	/*!
	 * \brief Causes the class to run the main execution flow. A call to this
	 * method will cause CORE to execute its functionalities as an independent
	 * component of the application.
	 *
	 * CORE will instantiate UI, Manager, WorkerDiscovery and Worker with
	 * parameters provided in the configuration file. Then all components will
	 * be run. CORE will finally wait for components to end their execution by
	 * joining them.
	 */
	void exec();
	/*!
	 * Gets configuration.
	 */
	static PeerConfiguration GetPeerConfiguration(std::string config_file)
			throw(CoreException);
	/*!
	 * Prints configuration.
	 */
	static std::string PrintPeerConfiguration(std::string config_file)
			throw(CoreException);
private:
	/*!
	 * Recoverer. Used to recover the queue of tasks in Worker when the
	 * application crashes. Actually there is no implememtation for this
	 * protocol.
	 */
	void exec_recovery(InetPort recovery_port);
	/*!
	 * Initialization sequence.
	 */
	void bonjour() throw(CoreException);
	/*!
	 * Opens configuration file.
	 */
	void CheckConfigFile() throw(CoreException);
	/*!
	 * Configuration file name. Path will be local.
	 */
	std::string _config_filename;
	/*!
	 * Logger postfix (peer id).
	 */
	std::string _logger_postfix;
	/*!
	 * Maintains the set of worker descriptors used by worker and discovery
	 * to send status and find best worker. PART OF PK
	 */
	PeersSet _peers_worker_descriptors;
	/*!
	 * Mutex for vector of worker descriptor. PART OF PK
	 */
	boost::mutex _peers_worker_descriptors_mutex;
	/*!
	 * Xml logger.
	 */
	logging::XmlSynLogger* _xml_logger;
}; /* CORE */
} /* middleware */

#endif
